package io.netty.channel;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;

/**
 *
 * ChannelInitializer：一个特殊的ChannelInboundHandler，它提供一种很简单的方法来初始化注册到EventLoop中的Channel;
 *
 * 该类的实现一般用在Bootstrap.handler()，ServerBootstrap.handler(),
 * ServerBootstrap.childHandler()用来构造Channel的ChannelPipeline
 * 注意该类使用了Sharable注解，所以他是一个可以安全的重用。
 *
 * Netty提供了ChannelInitializer类用来配置Channel的Handlers。
 * ChannelInitializer是通过ChannelPipeline来添加ChannelHandler的，如发送和接收消息
 * ChannelInitializer自身也是一个ChannelHandler，在添加完其他的handlers之后会自动从ChannelPipeline中删除自己
 */
@Sharable
public abstract class ChannelInitializer<C extends Channel> extends ChannelInboundHandlerAdapter {

    private static final InternalLogger logger = InternalLoggerFactory.getInstance(ChannelInitializer.class);

    /**
     * @param ch            the {@link Channel} which was registered.
     * @throws Exception    is thrown if an error occurs. In that case the {@link Channel} will be closed.
     */
    protected abstract void initChannel(C ch) throws Exception;

    @Override
    @SuppressWarnings("unchecked")
    public final void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        ChannelPipeline pipeline = ctx.pipeline();
        boolean success = false;
        try {
            ////调用用户定义的init函数对当前的channel进行初始化
            initChannel((C) ctx.channel());
            pipeline.remove(this);
            ctx.fireChannelRegistered();
            success = true;
        } catch (Throwable t) {
            logger.warn("Failed to initialize a channel. Closing: " + ctx.channel(), t);
        } finally {
            if (pipeline.context(this) != null) {
                pipeline.remove(this);
            }
            if (!success) {
                ctx.close();
            }
        }
    }
}
